package com.eis.persist.dao.util;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;

import com.eis.persist.model.function.PersistFunctionSchema;
import com.eis.thirdsys.connector.datatype.DataTypeList;
import com.eis.thirdsys.connector.datatype.datahandler.DataHandleUtil;
import com.eis.thirdsys.connector.datatype.eissystype.MysqlDataType;

public class FunctionDataBatchPreparedStatementSetter implements BatchPreparedStatementSetter {
	private static final Logger logger = LoggerFactory.getLogger(FunctionDataBatchPreparedStatementSetter.class);
	
	private ArrayList<HashMap<String, Object>> functionData;
	private List<PersistFunctionSchema> persistFunctionSchema;
	private int functionDBId;
	private Date dataFetchTime;
	private boolean isUpdate;
	private DataTypeList dataTypes;
	
	public FunctionDataBatchPreparedStatementSetter(ArrayList<HashMap<String, Object>> functionData, 
			List<PersistFunctionSchema> persistFunctionSchema, 
			int functionDBId, 
			Date dataFetchTime, 
			boolean isUpdate,
			DataTypeList dataTypes) {
		this.functionData = functionData;
		this.persistFunctionSchema = persistFunctionSchema;
		this.functionDBId = functionDBId;
		this.dataFetchTime = dataFetchTime;
		this.isUpdate = isUpdate;
		this.dataTypes = dataTypes;
	}
	
	@Override
	public void setValues(PreparedStatement ps, int i) throws SQLException {
		HashMap<String, Object> oneData = this.functionData.get(i);
		ps.setInt(1, functionDBId);
		ps.setTimestamp(2, new Timestamp(dataFetchTime.getTime()));
		
		if (oneData.get("eissysmainid") != null) {
			ps.setInt(persistFunctionSchema.size() + 3, (Integer) oneData.get("eissysmainid"));
		}
		
		int valueOffset = 3;
		int updateOnChangedFilterOffset = valueOffset + persistFunctionSchema.size() + 1;
		for(int j = 0; j < persistFunctionSchema.size(); j++) {
			PersistFunctionSchema oneField = persistFunctionSchema.get(j);
			Object handledData;
			try {
				handledData = DataHandleUtil.handleData(
						dataTypes.valueOf(oneField.getFieldType()).getHandlerClass(), 
						oneData.get(oneField.getFieldName()));
				
				if (handledData == null) handledData = "";
				
				if(dataTypes.valueOf(oneField.getFieldType()).getMysqlDataType().equals(MysqlDataType.VARCHAR)) {
					if (!(handledData instanceof String)) {
						handledData = handledData.toString();
					}
					
					ps.setString(j + valueOffset, (String) handledData);
					if(isUpdate) {
						ps.setString(j + updateOnChangedFilterOffset, (String) handledData);
						ps.setString(j + updateOnChangedFilterOffset + 1, (String) handledData);
						ps.setString(j + updateOnChangedFilterOffset + 2, (String) handledData);
					}
				} else if(dataTypes.valueOf(oneField.getFieldType()).getMysqlDataType().equals(MysqlDataType.INT)) {
					if (!(handledData instanceof Integer)) {
						String handledDataStr = handledData instanceof String ? (String) handledData : handledData.toString();
						try {
							handledData = Integer.parseInt(handledDataStr);
						} catch (Exception e) {
							handledData = 0;
						}
					}
					
					ps.setInt(j + valueOffset, (Integer) handledData);
					if(isUpdate) {
						ps.setInt(j + updateOnChangedFilterOffset, (Integer) handledData);
						ps.setInt(j + updateOnChangedFilterOffset + 1, (Integer) handledData);
						ps.setInt(j + updateOnChangedFilterOffset + 2, (Integer) handledData);
					}
				} else if(dataTypes.valueOf(oneField.getFieldType()).getMysqlDataType().equals(MysqlDataType.TINYINT)) {
					if (! (handledData instanceof Short)) {
						String handledDataStr = handledData instanceof String ? (String) handledData : handledData.toString();
						try {
							handledData = Short.parseShort(handledDataStr);
						} catch (Exception e) {
							handledData = (short) 0;
						}
					}
					
					int value = (Short) handledData;
					ps.setShort(j + valueOffset, (short)value);
					if(isUpdate) {
						ps.setShort(j + updateOnChangedFilterOffset, (short)value);
						ps.setShort(j + updateOnChangedFilterOffset + 1, (short)value);
						ps.setShort(j + updateOnChangedFilterOffset + 2, (short)value);
					}
				} else if(dataTypes.valueOf(oneField.getFieldType()).getMysqlDataType().equals(MysqlDataType.SMALLINT)) {
					if (! (handledData instanceof Short)) {
						String handledDataStr = handledData instanceof String ? (String) handledData : handledData.toString();
						try {
							handledData = Short.parseShort(handledDataStr);
						} catch (Exception e) {
							handledData = (short) 0;
						}
					}
					
					int value = (Short) handledData;
					ps.setShort(j + valueOffset, (short)value);
					if(isUpdate) {
						ps.setShort(j + updateOnChangedFilterOffset, (short)value);
						ps.setShort(j + updateOnChangedFilterOffset + 1, (short)value);
						ps.setShort(j + updateOnChangedFilterOffset + 2, (short)value);
					}
				} else if(dataTypes.valueOf(oneField.getFieldType()).getMysqlDataType().equals(MysqlDataType.MEDIUMBLOB)) {
					if (!(handledData instanceof String)) {
						handledData = handledData.toString();
					}
					
					ps.setString(j + valueOffset, (String) handledData);
					if(isUpdate) {
						ps.setString(j + updateOnChangedFilterOffset, (String) handledData);
						ps.setString(j + updateOnChangedFilterOffset + 1, (String) handledData);
						ps.setString(j + updateOnChangedFilterOffset + 2, (String) handledData);
					}
				} else if(dataTypes.valueOf(oneField.getFieldType()).getMysqlDataType().equals(MysqlDataType.DOUBLE)) {
					if (! (handledData instanceof Double)) {
						String handledDataStr = handledData instanceof String ? (String) handledData : handledData.toString();
						try {
							handledData = Double.parseDouble(handledDataStr);
						} catch (Exception e) {
							handledData = (double) 0;
						}
					}
					
					ps.setDouble(j + valueOffset, (Double) handledData);
					if(isUpdate) {
						ps.setDouble(j + updateOnChangedFilterOffset, (Double) handledData);
						ps.setDouble(j + updateOnChangedFilterOffset + 1, (Double) handledData);
						ps.setDouble(j + updateOnChangedFilterOffset + 2, (Double) handledData);
					}
				} else if(dataTypes.valueOf(oneField.getFieldType()).getMysqlDataType().equals(MysqlDataType.MEDIUMINT)) {
					if (!(handledData instanceof Integer)) {
						String handledDataStr = handledData instanceof String ? (String) handledData : handledData.toString();
						try {
							handledData = Integer.parseInt(handledDataStr);
						} catch (Exception e) {
							handledData = 0;
						}
					}
					
					ps.setInt(j + valueOffset, (Integer) handledData);
					if(isUpdate) {
						ps.setInt(j + updateOnChangedFilterOffset, (Integer) handledData);
						ps.setInt(j + updateOnChangedFilterOffset + 1, (Integer) handledData);
						ps.setInt(j + updateOnChangedFilterOffset + 2, (Integer) handledData);
					}
				} else if (dataTypes.valueOf(oneField.getFieldType()).getMysqlDataType().equals(MysqlDataType.TEXT)) {
					if (!(handledData instanceof String)) {
						handledData = handledData.toString();
					}
					ps.setString(j + valueOffset, (String) handledData);
					if(isUpdate) {
						ps.setString(j + updateOnChangedFilterOffset, (String) handledData);
						ps.setString(j + updateOnChangedFilterOffset + 1, (String) handledData);
						ps.setString(j + updateOnChangedFilterOffset + 2, (String) handledData);
					}
				} else if (dataTypes.valueOf(oneField.getFieldType()).getMysqlDataType().equals(MysqlDataType.DATETIME)) {
					if (handledData instanceof Date) {
						ps.setDate(j + valueOffset, new java.sql.Date(((Date) handledData).getTime()));
						if(isUpdate) {
							ps.setDate(j + updateOnChangedFilterOffset, new java.sql.Date(((Date) handledData).getTime()));
							ps.setDate(j + updateOnChangedFilterOffset + 1, new java.sql.Date(((Date) handledData).getTime()));
							ps.setDate(j + updateOnChangedFilterOffset + 2, new java.sql.Date(((Date) handledData).getTime()));
						}
					}
				}
				
				updateOnChangedFilterOffset += 2;
			} catch (InstantiationException e) {
				logger.error("Exception: ", e);
			} catch (IllegalAccessException e) {
				logger.error("Exception: ", e);
			}
		}
	}

	@Override
	public int getBatchSize() {
		return functionData.size();
	}
}
